import bind from "./helpers/bind";

const toString = Object.prototype.toString;

// 判断值是不是数组
function isArray(val) {
  return toString.call(val) === '[object Array]';
}

// 判断值是不是 undefined
function isUndefined(val) {
  return typeof val === 'undefined';
}

// 判断值是不是字符串
function isString(val) {
  return typeof val === 'string';
}

// 判断值是不是数字
function isNumber(val) {
  return typeof val === 'number';
}

// 判断值是不是对象
function isObject(val) {
  return val !== null && typeof val === 'object';
}

// 判断值是不是继承对象
function isPlainObject(val) {
  if (toString.call(val) !== '[object Object]') {
    return false;
  }
  var prototype = Object.getPrototypeOf(val);
  return prototype === null || prototype === Object.prototype;
}

// 判断值是不是日期
function isDate(val) {
  return toString.call(val) === '[object Date]';
}

// 判断值是不是方法
function isFunction(val) {
  return toString.call(val) === '[object Function]';
}

// 去掉字符串开始和结束的空格
function trim(str) {
  return str.replace(/^\s*/, '').replace(/\s*$/, '');
}

// 扩展请求方法到原型链
function extend(_to, _from) {
	const requestAPI = ['request', 'get', 'delete', 'head', 'options', 'post', 'put', 'patch', '_requestMethodWithData', '_requestMethodWithoutData']
	for (const key in _from) {
		_to[key] = _from[key]
	}
	requestAPI.forEach(key => {
		_to[key] = _from[key]
	})
	return _to
}

// 多个对象深度合并并返回结果
function merge(/* obj1, obj2, obj3, ... */) {
  var result = {};
  function assignValue(val, key) {
    if (isPlainObject(result[key]) && isPlainObject(val)) {
      result[key] = merge(result[key], val);
    } else if (isPlainObject(val)) {
      result[key] = merge({}, val);
    } else if (isArray(val)) {
      result[key] = val.slice();
    } else {
      result[key] = val;
    }
  }
  for (var i = 0, l = arguments.length; i < l; i++) {
    forEach(arguments[i], assignValue);
  }
  return result;
}

// 每个项的函数的数组或对象进行迭代
function forEach(obj, fn) {
  if (obj === null || typeof obj === 'undefined') {
    return;
  }
  if (typeof obj !== 'object') {
    obj = [obj];
  }
  if (isArray(obj)) {
    for (var i = 0, l = obj.length; i < l; i++) {
      fn.call(null, obj[i], i, obj);
    }
  } else {
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        fn.call(null, obj[key], key, obj);
      }
    }
  }
}

function flattenHeaders(headers, method) {
	if (!headers) {
		return headers
	}
	headers = merge(headers.common || {}, headers[method] || {}, headers)
	const methodsToDelete = ['delete', 'get', 'head', 'options', 'post', 'put', 'patch', 'common']
	methodsToDelete.forEach(method => {
		delete headers[method]
	})
	return headers
}

module.exports = {
  isArray,
  isUndefined,
  isString,
  isNumber,
  isObject,
  isPlainObject,
  isDate,
  isFunction,
  trim,
  extend,
  merge,
  forEach,
  flattenHeaders
}